package net.lbh.xf.speech;

import java.util.Calendar;
import java.util.Date;

import com.iflytek.cloud.ErrorCode;
import com.iflytek.cloud.InitListener;
import com.iflytek.cloud.Setting;
import com.iflytek.cloud.SpeechConstant;
import com.iflytek.cloud.SpeechError;
import com.iflytek.cloud.SpeechEvent;
import com.iflytek.cloud.SpeechSynthesizer;
import com.iflytek.cloud.SpeechUtility;
import com.iflytek.cloud.SynthesizerListener;

import android.app.Activity;
import android.content.Context;
import android.media.AudioManager;
import android.os.Bundle;
import android.os.Environment;
import android.os.SystemClock;

/**
 * 
 * 科大讯飞 语音合成
 * 
 * @author Lbh
 * @date 2015-9-4 上午12:33:11
 * @update (date)
 * @version V1.0
 */

public class XfSpeechAgent {

	private static final String TAG = XfSpeechAgent.class.getName();

	private static volatile XfSpeechAgent instance;
	private Context mContext;
	private Context mAppContext;
	private static String LICENCE_FILE_NAME;

	/***** 设置合成速度 */
	public static String DEFAULT_SPEED = "50";
	/***** 设置合成音调 */
	public static String DEFAULT_PITCH = "50";
	/***** 设置合成音量 */
	public static String DEFAULT_VOLUME = "50";
	/***** 设置播放器音频流类型 */
	public static String DEFAULT_STREAM_TYPE = "3";

	/***** 在线合成发音人 */
	public static Voicer DEFAULT_VOICE_NAME = Voicer.XIAOQI;

	public static String API_KEY;
	public static String API_SECRET_KEY;
	public static String APP_ID;

	private SpeechSynthesizer mSpeechSynthesizer;

	private boolean isInitEngine;

	public static enum Voicer {
		XIAOYAN("xiaoyan"), XIAOYU("xiaoyu"), CATHERINE("catherine"), HENRY(
				"henry"), VIMARY("vimary"), VIXY("vixy"), XIAOQI("xiaoqi"), VIXF(
				"vixf"), XIAOMEI("xiaomei"), XIAOLIN("xiaolin"), XIAORONG(
				"xiaorong"), XIAOQIAN("xiaoqian"), XIAOKUN("xiaokun"), XIAOQIANG(
				"xiaoqiang"), VIXYING("vixying"), XIAOXIN("xiaoxin"), NANNAN(
				"nannan"), VILS("vils");

		private final String value;

		Voicer(String value) {
			this.value = value;
		}

		@Override
		public String toString() {
			return this.value;
		}
	}

	public static XfSpeechAgent getInstance() {
		
		if (instance == null) {
		
			synchronized (XfSpeechAgent.class) {
				
				if (instance == null) {
					instance = new XfSpeechAgent();
				}
				
			}
		}
		return instance;
	}

	private XfSpeechAgent() {
	}

	public void init(Context context, String appId) {
		this.mContext = context;
		this.mAppContext = context.getApplicationContext();

		initKeys(appId);

		// 注意： appid 必须和下载的SDK保持一致，否则会出现10407错误
		SpeechUtility.createUtility(this.mAppContext, "appid=" + APP_ID);

		configWorkDir();
	}

	public void setDebug(boolean isDebug) {
		L.isDebug = isDebug;
		// 以下语句用于设置日志开关（默认开启），设置成false时关闭语音云SDK日志打印
		Setting.setShowLog(L.isDebug);
	}

	public void initKeys(String appId) {
		APP_ID = appId;
	}

	/**
	 * 
	 * 初始化key
	 * 
	 * @param appId
	 * @param appKey
	 * @param appSecret
	 * @return void
	 * @autour Lbh
	 * @date 2015-8-23 下午8:49:47
	 * @update (date)
	 */
	public void initKeys(String appId, String appKey, String appSecret) {
		APP_ID = appId;
		API_KEY = appKey;
		API_SECRET_KEY = appSecret;
	}

	/**
	 * 
	 * 设置 语音 使用 本地目录，（确定有读�?权限�?
	 * 
	 * @return void
	 * @autour Lbh
	 * @date 2015-8-23 下午8:41:07
	 * @update (date)
	 */
	public void configWorkDir() {
		// LICENCE_FILE_NAME = FileUtils.getFileCachePath(mAppContext)
		// + "/msc/tts.wav";
		LICENCE_FILE_NAME = Environment.getExternalStorageDirectory()
				+ mContext.getPackageName() + "/msc/"+System.currentTimeMillis()+"tts.wav";
	}

	public boolean isInitSpeechEngine() {
		return isInitEngine;
	}

	/**
	 * 
	 * 初始�?语音 引擎
	 * 
	 * @param activity
	 * @param listener
	 * @return boolean
	 * @autour Lbh
	 * @date 2015-8-23 下午9:02:26
	 * @update (date)
	 */
	public void initSpeechEngine(Context context, InitListener listener) {
		mSpeechSynthesizer = SpeechSynthesizer.createSynthesizer(context,
				listener);
	}

	public void initSpeechEngine(Context context) {
		initSpeechEngine(context, new InitListener() {

			@Override
			public void onInit(int code) {
				L.d(TAG, "InitListener init() code = " + code);
				if (code != ErrorCode.SUCCESS) {
					L.d(TAG, "init failed code:" + code);
				} else {
					isInitEngine = true;
					// 初始化成功，之后可以调用startSpeaking方法
					// 注：有的开发者在onCreate方法中创建完合成对象之后马上就调用startSpeaking进行合成，
					// 正确的做法是将onCreate中的startSpeaking调用移至这里
				}
			}
		});
	}

	/**
	 * 
	 * 设置 播音员
	 * 
	 * @param voicer
	 * @return void
	 * @autour Lbh
	 * @date 2015-9-4 上午11:26:54
	 * @update (date)
	 */
	public void setVoicer(Voicer voicer) {
		DEFAULT_VOICE_NAME = voicer;
	}

	public void setParam(Voicer voicer, String speed) {
		DEFAULT_VOICE_NAME = voicer;
		DEFAULT_SPEED = speed;
	}

	/**
	 * 参数设置
	 * 
	 * @param param
	 * @return
	 */
	private void setParam() {
		L.d(TAG, " ----  setParam ---- ");
		L.d(TAG, " ----  setParam ---- VOICE_NAME:" + DEFAULT_VOICE_NAME.toString());
		L.d(TAG, " ----  setParam ---- PITCH:" + DEFAULT_PITCH);
		L.d(TAG, " ----  setParam SPEED: ---- " + DEFAULT_SPEED);

		// 清空参数
		mSpeechSynthesizer.setParameter(SpeechConstant.PARAMS, null);
		// 根据合成引擎设置相应参数
		if (SpeechConstant.TYPE_CLOUD.equals(SpeechConstant.TYPE_CLOUD)) {
			mSpeechSynthesizer.setParameter(SpeechConstant.ENGINE_TYPE,
					SpeechConstant.TYPE_CLOUD);
			// 设置在线合成发音人
			mSpeechSynthesizer.setParameter(SpeechConstant.VOICE_NAME,
					DEFAULT_VOICE_NAME.toString());
		} else {
			mSpeechSynthesizer.setParameter(SpeechConstant.ENGINE_TYPE,
					SpeechConstant.TYPE_LOCAL);
			// 设置本地合成发音人 voicer为空，默认通过语记界面指定发音人。
			mSpeechSynthesizer.setParameter(SpeechConstant.VOICE_NAME,
					DEFAULT_VOICE_NAME.toString());
		}
		// 设置合成语速
		mSpeechSynthesizer.setParameter(SpeechConstant.SPEED, DEFAULT_SPEED);
		// 设置合成音调
		mSpeechSynthesizer.setParameter(SpeechConstant.PITCH, DEFAULT_PITCH);
		// 设置合成音量
		mSpeechSynthesizer.setParameter(SpeechConstant.VOLUME, DEFAULT_VOLUME);
		// 设置播放器音频流类型
		mSpeechSynthesizer.setParameter(SpeechConstant.STREAM_TYPE,
				DEFAULT_STREAM_TYPE);

		// 设置播放合成音频打断音乐播放，默认为true
		mSpeechSynthesizer.setParameter(SpeechConstant.KEY_REQUEST_FOCUS,
				"true");

		// 设置音频保存路径，保存音频格式支持pcm、wav，设置路径为sd卡请注意WRITE_EXTERNAL_STORAGE权限
		// 注：AUDIO_FORMAT参数语记需要更新版本才能生效
		mSpeechSynthesizer.setParameter(SpeechConstant.AUDIO_FORMAT, "wav");
		mSpeechSynthesizer.setParameter(SpeechConstant.TTS_AUDIO_PATH,
				LICENCE_FILE_NAME);
	}

	/**
	 * 播报 语音
	 * 
	 * @param msg
	 * @return void
	 * @autour Lbh
	 * @date 2015-9-4 上午12:52:39
	 * @update (date)
	 */
	public int speak(String msg) {

		return speak(msg, new CustomSynthesizerListener());
	}

	/**
	 * 
	 * 播报语音
	 * 
	 * @param msg
	 * @param listener
	 * @return void
	 * @autour Lbh
	 * @date 2015-9-4 上午1:00:03
	 * @update (date)
	 */
	public int speak(String msg, SynthesizerListener listener) {

		if (mSpeechSynthesizer == null) {
			if (mAppContext!=null) {
				initSpeechEngine(mAppContext);
			}else {
				throw new IllegalArgumentException(
						" please call initSpeechEngine method! ");
			}
		}
		L.d(TAG, " ----  speak ---- msg :" + msg);
		setParam();

		return mSpeechSynthesizer.startSpeaking(msg, listener);
	}

	public void pause() {

		if (mSpeechSynthesizer != null) {
			mSpeechSynthesizer.pauseSpeaking();
		}
	}

	public void resume() {

		if (mSpeechSynthesizer != null) {
			mSpeechSynthesizer.resumeSpeaking();
		}
	}

	public void cancel() {

		if (mSpeechSynthesizer != null) {
			mSpeechSynthesizer.stopSpeaking();
		}
	}

	public void setVolumeControlStream(Activity mActivity) {
		mActivity.setVolumeControlStream(AudioManager.STREAM_MUSIC);
	}

	public class CustomSynthesizerListener implements SynthesizerListener {

		@Override
		public void onSpeakBegin() {
			L.d(TAG, "开始播放");
		}

		@Override
		public void onSpeakPaused() {
			L.d(TAG, "暂停播放");
		}

		@Override
		public void onSpeakResumed() {
			L.d(TAG, "继续播放");
		}

		@Override
		public void onBufferProgress(int percent, int beginPos, int endPos,
				String info) {
			// 合成进度
			L.d(TAG, "---  progress --合成进度-- percent:" + percent);
		}

		@Override
		public void onSpeakProgress(int percent, int beginPos, int endPos) {
			// 播放进度
			L.d(TAG, "---  progress -- 播放进度-- percent:" + percent);
		}

		@Override
		public void onCompleted(SpeechError error) {
			if (error == null) {
				L.d(TAG, "播放完成！");
			} else if (error != null) {
				L.d(TAG, error.getPlainDescription(true));
			}
		}

		@Override
		public void onEvent(int eventType, int arg1, int arg2, Bundle obj) {
			if (obj != null) {
				String sid = obj.getString(SpeechEvent.KEY_EVENT_SESSION_ID);
			}
			L.d(TAG, "--- onEvent--- eventType:" + eventType);
			// 以下代码用于获取与云端的会话id，当业务出错时将会话id提供给技术支持人员，可用于查询会话日志，定位出错原因
			// 若使用本地能力，会话id为null
			// if (SpeechEvent.EVENT_SESSION_ID == eventType) {
			// String sid = obj.getString(SpeechEvent.KEY_EVENT_SESSION_ID);
			// Log.d(TAG, "session id =" + sid);
			// }
		}
	};
}
